/**
 * Map遍历的时候能保证顺序相同(帧同步中可以使用)
 * @date 2024.9.10
 * @author wz
 */
export class ArrayMap<K, V> {
    /**
     * 保存实际数据
     */
    private _arr: V[] = [];
    
    /**
     * 保存键的有序数组，保持插入顺序
     */
    private _keys: K[] = [];
    
    /**
     * 保存key对应arr中的索引
     */
    private _map: Map<K, number> = new Map();

    /**
     * 实际数据长度
     */
    public get length(): number {
        return this._arr.length;
    }

    /**
     * 获取所有值，按插入顺序
     */
    public get values(): V[] {
        return [...this._arr]; // 返回副本以避免外部修改
    }

    /**
     * 获取所有键，按插入顺序
     */
    public get keys(): K[] {
        return [...this._keys]; // 返回副本以避免外部修改
    }

    /**
     * 构造函数
     */
    constructor() {
        this._arr = [];
        this._keys = [];
        this._map = new Map();
    }

    /**
     * 设置键值对
     * @param key 键
     * @param value 值
     * @returns 返回this以支持链式调用
     */
    set(key: K, value: V): ArrayMap<K, V> {
        const index = this._map.get(key);
        if (index !== undefined) {
            // 如果键已存在，更新值
            this._arr[index] = value;
        } else {
            // 如果是新键，添加到数组末尾
            this._arr.push(value);
            this._keys.push(key);
            this._map.set(key, this._arr.length - 1);
        }
        return this;
    }

    /**
     * 获取值
     * @param key 键
     * @returns 值或undefined
     */
    get(key: K): V | undefined {
        const index = this._map.get(key);
        if (index !== undefined && index >= 0 && index < this._arr.length) {
            return this._arr[index];
        }
        return undefined;
    }

    /**
     * 检查键是否存在
     * @param key 键
     * @returns 是否存在
     */
    has(key: K): boolean {
        return this._map.has(key);
    }

    /**
     * 删除键值对
     * @param key 键
     * @returns 是否删除成功
     */
    delete(key: K): boolean {
        const index = this._map.get(key);
        if (index === undefined) {
            return false;
        }

        // 删除指定索引的元素
        this._arr.splice(index, 1);
        this._keys.splice(index, 1);
        this._map.delete(key);

        // 更新后面元素的索引
        for (let i = index; i < this._keys.length; i++) {
            this._map.set(this._keys[i], i);
        }
        
        return true;
    }

    /**
     * 清空所有键值对
     */
    clear(): void {
        this._arr = [];
        this._keys = [];
        this._map.clear();
    }

    /**
     * 遍历所有键值对，按插入顺序
     * @param callbackfn 回调函数
     */
    forEach(callbackfn: (value: V, key: K, map: ArrayMap<K, V>) => void): void {
        for (let i = 0; i < this._keys.length; i++) {
            callbackfn(this._arr[i], this._keys[i], this);
        }
    }

    /**
     * 获取迭代器，按插入顺序
     */
    [Symbol.iterator](): Iterator<[K, V]> {
        let index = 0;
        
        return {
            next: (): IteratorResult<[K, V]> => {
                if (index < this._keys.length) {
                    const key = this._keys[index];
                    const value = this._arr[index];
                    index++;
                    return {
                        done: false,
                        value: [key, value]
                    };
                }
                return { done: true, value: undefined as any };
            }
        };
    }
}